First Laboratory

Microstrucutres and Trading Systems



Bryan Manica Pineda

if722176@iteso.mx

June. 2022 | Repository: Link


OrderBook and Public Trades metrics

A quantitative descriptive analysis


Abstract

La intención del desarrollo de este proyecto es brindar las herramientas necesarias para la obtención de algunas métricas específicas que ayuden a entender de mejor manera la **microestructura** de mercados de una activo en particular. El desarrollo del mismo se divide en varias etapas, una la cual define toda la _arquitectura_ de archivos que permitan al usuario obtener dichos cálculos de manera efectiva y concisa, otra que ayude a la gestión de visualizaciones de alto nivel y finalmente una etapa de presentación de resultados, mostrado la aplicación, funcionalidad y línea de análisis del proyecto.


1. Introduction


El desarrollo de este proyecto tiene una línea de análisis particular, y su principal objetivo se centra en la implementación de una esquema funcional para el cálculo de ciertas métricas claves que ayuden a entender de una mejor manera la microestructura de mercado correspondiente a un activo o activos en concreto. A través de las herramientas desarrolladas se espera que un nuevo y potencial usuario pueda llegar a utilizar todo la arquitectura planteada en su proceso de estudio de mercado. La intención primordial de este notebook es proveer de un ejemplo guíado que sea gráfico y visual sobre las aplicaciones y la estructura que se estuvo desarrollando a lo largo del trabajo.


2. Install/Load Packages and Depedencies


2.1 Python Packages

Para poder correr el presente notebook es necesario haber instalado todas aquellas librerias que se encuentran descritas en el archivo adjunto en el repositorio con nombre requirements.txt. Dichas dependencias son las siguientes:

  • pandas >= 1.1.0
  • numpy >= 1.19.1
  • jupyter >= 1.0.0
  • chart_studio >= 1.1
  • plotly >= 4.14
  • scipy >= 1.8.1

2.2 Files Dependencies

Además de todas las librerias previamente mencionadas, el correcto funcionamiento de este notebook también requiere de algunos datos externos. Estos archivos se encuentran directamente en la carpeta files adjunta dentro de este mismo repositorio:

  • files/orderbooks_05jul21.json: Archivo tipo json. Datos históricos de diversos orderbooks.
  • files/btcusdt_binance.csv: Archivo tipo csv. Datos históricos respecto a los public trades de BTCUSDT.

2.3 Install Packages

En caso de que no se hayan instalado los paquetes dentro del ambiente virtual sobre el cual se está trabajando, se pueden instalar directamente dentro de este cuaderno. A continuación se encuentra la estructura de comandos necesarias para instalar las librerias, solo correr en caso de que no se hayan instalado previamente:

In [ ]:
%%capture

### Install all the pip packages in the requirements.txt
import sys
!{sys.executable} -m pip install -r requirements.txt

2.4 Load Packages and Scripts

Ya con los requerimentos computacionales bien definidos, ahora se proseguirá a cargar tanto las librerias como los scripts de python 3 para poder realizar el análisis correspondiente.

In [1]:
### Requierd packages
import pandas as pd
import numpy as np
import warnings

### Requierd local scripts
import data as dt
import functions as fn
import visualizations as vz


3. Data Description


Para poder realizar este laboratorio en particular, se nos fueron proporcionados los datos previamente mencionados. A continuación se comenzará a describir un poco más a detalle la estructura de los mismos para entender de mejor manera la materia prima sobre la cual se estará trabajando.

Order Book.

Este primer conjunto de datos se encuentra bajo el formato json, por tanto se compone por una lista de diccionarios donde cada subconjuto de valores responde a un libro de órdenes del activo con clave de pizarra BTCUSDT, dicho orderbook se encuentra asociado a cada punto del tiempo que representa la llave del diccionario. La actualización de dichos libros se da en términos de segundos, por lo tanto la ventana de tiempo sobre la cual trabajaremos es de un poco más de $1$ hora. A pesar de que pareciera que no tenemos tantos datos, la realidad es que cada libro cuenta con una cantidad suficiente de datos para poder extraer información relevante a ese punto del tiempo que se encuentra asociado.

Public Trades.

Este segundo y último conjunto de datos se encuentra en formato csv, y básicamente hace referencia a los movimientos de mercado (trades) que se realizan en cada punto del tiempo, nuevamente aquí estamos trabajando con aquellos datos donde hubo una conexión entre la parte compradora y la parte vendedora del mercado para el activo BTCUSDT, es decir, en estos nuevos datos contamos con la información de aquellas órdenes que sí fueron empatadas por lo tanto estas operaciones que se efectuan son las que al final del día terminan teniendo un impacto directo en la fluctuación del precio para el activo analizado. La ventana de tiempo para la cual disponemos de esta información se encuentra alrededor de $1$ día.

3.1. Order Book

Ya sabemos entonces que contamos con una lista de diccionarios donde cada llave representa un punto en el tiempo donde se contaba con ese determinado libro de órdenes, ahora lo que haremos será ir definiendo y mostrando un poco mas sobre los datos ya desde una perspectiva un poco más visual.

In [2]:
### Let's visualize the keys range.
ob_data = dt.ob_data_bit
range_ob = pd.to_datetime(pd.Series(list(ob_data.keys()))).sort_values()
print(f'El primer tiempo registrado está en: {range_ob[0]}, y el último en: {range_ob.tail(1).item()}')
El primer tiempo registrado está en: 2021-07-05 13:06:46.571000+00:00, y el último en: 2021-07-05 14:06:46.412000+00:00

Como podemos observar ya directamente de la descripción de los rangos para las llaves de los orderbooks contamos con un poco menos de $1$ hora de información correspondiente al día 2021-07-05 entre $1$ y $2$ de la tarde.

In [3]:
### Let's see how many books do we have
print(f'En una hora de tiempo contamos con {len(list(ob_data.keys())):,} libros')
En una hora de tiempo contamos con 2,401 libros

Entonces si bien pareciera que $1$ hora de tiempo no puede aportar mucha información, la realidad es que dentro de este horario contamos con alrededor de $2,401$ libros. A continuación se mostrará un poco respecto al contenido de cada orderbook, esto con la intención de alcanzar a percibir la cantidad de datos que tenemos.

In [4]:
### Let's see the first orderbook values
print(f'Este primer orderbook corresponde al punto en el tiempo. {range_ob[0]}:')
list(ob_data.values())[0].head(5)
Este primer orderbook corresponde al punto en el tiempo. 2021-07-05 13:06:46.571000+00:00:
Out[4]:
bid_size bid ask ask_size
0 0.000400 28270.0 28275.0 0.025405
1 0.009787 28269.0 28276.0 0.516810
2 0.008168 28268.0 28277.0 0.005044
3 0.995787 28266.0 28278.0 0.377374
4 1.038704 28265.0 28280.0 1.179715

Como podemos percibir del dataframe correspondiente al primer punto del tiempo, contamos con diferentes atributos:

  • bid_size: Corresponde al volumen posicionado al del bid asociado.
  • bid: Responde directamente al precio más alto que un comprador esta dispuesto a pagar por el activo de interés.
  • ask: Es el precio más bajo al cual un vendedor esta dispuesto a vender el activo.
  • ask_size: Corresponde al volumen posicionado al del ask asociado.

Todas y cada una de las llaves correspondientes a los datos del orderbook contienen un dataframe con las mismas características que se encuentra desplegado. Entonces a partir de estos valores es que se calculan las métricas que serán explicadas en la sección $4$ del documento.

3.2. Public Trades

Los trades públicos de cierta manera se encuentran contenidos en una estructura de datos mucho más amigable para la mayoría (csv), por tanto python se encarga de leer estos archivos y directamente transformarlos en un dataframe. A continuación observaremos un poco respecto a los atributos y dimensionas que trae consigo este archivo.

In [5]:
### Let's visualize the df range.
pt_data = dt.pt_data
range_pt = pd.to_datetime(pt_data.timestamp).sort_values()
print(f'El primer tiempo registrado está en: {range_pt.head(1).item()}, y el último en: {range_pt.tail(1).item()}')
El primer tiempo registrado está en: 2022-05-10 00:00:12, y el último en: 2022-05-10 23:59:38

Como podemos observar directamente de los rangos de tiempo para los public trades, vemos que el primer registro se efectuó en la madrugada del 2022-05-10 y el último de ellos se dió el mismo día justo antes de que termine, por lo tanto para este conjunto de información contamos con todo un día de transacciones.

In [6]:
### Let's see the public trades dataframe
print(f'Los public trades con los que contamos tienen un total de {pt_data.shape[0]:,} filas')
pt_data.head()
Los public trades con los que contamos tienen un total de 286,600 filas
Out[6]:
timestamp price amount side
0 2022-05-10 08:08:07 31702.47 0.00035 sell
1 2022-05-10 08:08:07 31702.48 0.00263 buy
2 2022-05-10 08:08:07 31702.48 0.00631 buy
3 2022-05-10 08:08:07 31702.48 0.00264 buy
4 2022-05-10 08:08:07 31702.48 0.01146 buy

Del registro de transacciones para el BTCUSDT contamos con un total de $286,000$ operaciones, las cuales se encuentran dividas a lo largo de un día, en cuanto a los atributos del data frame contamos con el tiempo, el precio al cual se hizo la conexión, el volumen transaccionado a dicho precio en ese punto del tiempo, y finalmente contamos con la estructura de venta o compra lo cual indica de que lado se efectuó la operación.


4. Order Book Metrics


Con la intención de eficientar tiempos computacionales lo que se decide hacer es trabajar sobre diversos scripts de python los cuales contienen las funciones predeterminadas para el cálculo de las métricas.

En esta primera serie de cálculos definidos para los orderbooks se generó una función la cual tiene la capacidad de indagar sobre las profundidades de cada libro de órdenes (claro para aquellas métricas que así lo permiten). Por términos prácticos para este laboratorio solo se estará explorando los valores obtenidos a tráves del Top of the book de manera que se deja al potencial usuario de estas funciones el poder explorar las funcionalidades sobre la profundidad de los orderbooks.

In [7]:
### Let's define all the metric calculations.
ob_metrics = fn.get_ob_metrics(ob_data) # Without ob dept defined
ob_metrics_depth = fn.get_ob_metrics(ob_data, 5) # With a ob depth of 5

print(f'The keys for this ob metrics are: {list(ob_metrics.keys())}')
The keys for this ob metrics are: ['update_median', 'price_levels', 'bid_volume', 'ask_volume', 'total_volume', 'spread', 'midprice', 'volume_inbalance', 'weighted_mid', 'vwap', 'stats_moments', 'ohlcv']

4.1. Median Time OrderBook to Update

Esta primera métrica lo que nos describe es la mediana de tiempo que requiere cada libro de órdenes para que este se actualice, es decir a partir de este valor podemos nosotros encontrar el punto medio de la distribución para el cambio/actualización de los orderbooks. Las ventajas de utilizar la mediana sobre el promedio responden escencialmente a la presencia de valores extremos, así podemos minimizar el riesgo de sesgo para esta métrica.

In [8]:
### Let' see the first metric
update_median = int(ob_metrics['update_median'])
print(f'La mediana de tiempo para que se actualice un ob es de: {update_median:,} milisegundos')
La mediana de tiempo para que se actualice un ob es de: 1,500 milisegundos

De la mediana de tiempo podemos notar que los orderbooks se actualizan aproximadamente cada $1,500$ milisegundos, esto nos puede dar indicios para empezar a percibir la líquidez del activo analizado, el cual recordemos se trata de BTCUSDT.

4.2. Price Levels

Los niveles en cada orderbook es una medida que no requiere de gran explicación, básicamente lo que nos describe es cuantos órdenes son colocadas para cada libro de órdenes.

In [9]:
### Let's see the price levels
price_levels = pd.DataFrame.from_dict(ob_metrics['price_levels']).T
price_levels.columns=['Price Levels']
price_levels.head()
Out[9]:
Price Levels
2021-07-05T13:06:46.571Z 25
2021-07-05T13:06:47.918Z 25
2021-07-05T13:06:49.414Z 25
2021-07-05T13:06:51.077Z 25
2021-07-05T13:06:52.426Z 25

De los niveles que tiene cada orderbook del activo analizado podemos observar que prácticamente cada ventana de tiempo cuenta con la misma cantidad de órdenes colocadas, $25$.

4.3. Bid Volume

Como previamente se comentó el Bid corresponde al precio más alto que un comprador esta dispuesto a pagar por el activo de interés, entonces con esto en cuenta podemos decir que al nosotros obtener el volumen total de las órdenes que se estan colocando en cada orderbook para la parte Bid, podemos definir entonces la "euforia" que puede llegar a existir por parte de los compradores, a medida que más alto sea, nos indica el aumento de interés en el activo. Podemos describir este valor matemáticamente como:

$$\sum_{i=1}^{n} \text{bid size}$$

Donde cada elemento $i$ representa una ventana de tiempo y $\text{bid size}$ el volumen de órdenes posicionadas por los compradores para el activo de interés.

In [10]:
### Let's see the bid volume levels
bid_volume = pd.DataFrame.from_dict(ob_metrics['bid_volume']).T
bid_volume.columns=['Bid Volume']
bid_volume.head()
Out[10]:
Bid Volume
2021-07-05T13:06:46.571Z 32.100178
2021-07-05T13:06:47.918Z 32.100178
2021-07-05T13:06:49.414Z 32.100178
2021-07-05T13:06:51.077Z 36.263315
2021-07-05T13:06:52.426Z 36.263315

A simple vista pudiera llegar a parecer que el volumen de bid se mantiene estable, sin embargo, la realidad es que este valor se encuentra flúctuando a tráves del tiempo, las expectativas y la euforia de comprar no son estables sobre todo en activos tan volátiles como el que se está analizando.

4.4. Ask Volume

El ask volume responde a una situación muy similar a la del bid volume solo que ahora lo hace desde la perspectiva del vendedor, nos habla de que tanto se esta dispuesto a vender en el mercado y que tantas "ganas" de liquidar las posiciones existe en determinado punto del tiempo. Matemáticamente se expresa muy parecido al bid volume

$$\sum_{i=1}^{n} \text{ask size}$$

Donde cada elemento $i$ representa una ventana de tiempo y $\text{ask size}$ el volumen de órdenes posicionadas por los vendedores para el activo de interés.

In [11]:
### Let's see the ask volume levels
ask_volume = pd.DataFrame.from_dict(ob_metrics['ask_volume']).T
ask_volume.columns=['Ask Volume']
ask_volume.head()
Out[11]:
Ask Volume
2021-07-05T13:06:46.571Z 31.699457
2021-07-05T13:06:47.918Z 31.699457
2021-07-05T13:06:49.414Z 31.699457
2021-07-05T13:06:51.077Z 36.929183
2021-07-05T13:06:52.426Z 36.929183

Haciendo una rápida comparativa con el bid volume, si nostros observamos que el ask volume empieza a crecer radicalmente podriamos empezar a concluir que existe cierto grado de incertidumbre en el activo. Altos volumenes de personas que quieren vender pueden llegar a generar caídas importantes en el precio.

4.5. Total Volume

El total volume básicamente es la suma de bid volume y ask volume:

$$\sum_{i=1}^{n} \text{bid size} + \text{ask size}$$
In [12]:
### Let's see the total volume levels
total_volume = pd.DataFrame.from_dict(ob_metrics['total_volume']).T
total_volume.columns=['Total Volume']
total_volume.head()
Out[12]:
Total Volume
2021-07-05T13:06:46.571Z 63.799635
2021-07-05T13:06:47.918Z 63.799635
2021-07-05T13:06:49.414Z 63.799635
2021-07-05T13:06:51.077Z 73.192498
2021-07-05T13:06:52.426Z 73.192498

El volumen total puede llegar a tener conclusiones interesantes, si bien no nos da la perspectiva respecto a las posiciones en el mercado si nos pueda ayudar a definir el interés particular que existe por el activo en cada momento del tiempo, de manera que mientrás más elevado sea este valor, podemos decir que existe algún fenómeno que esta causando expectativas (pueden ser positivas o negativas).

4.6. Spread

El spread es uno de los principales indicadores de liquidez, básicamente lo que nos define es que tal lejos están de ponerse de acuerdo la parte vendedora y la parte compradora en cada punto del tiempo. Este valor solo se define para el top of the book el cual representa el mejor bid y el mejor ask disponible en cada libro de órdenes. Matemáticamente se describe de la siguiente manera.

$$\hat{\text{ask price}} - \hat{\text{bid price}}$$

Donde el simbolo $\hat{}$ hace alución a la presencia del mejor valor disponible en cada momento.

In [13]:
### Let's see the spread for top of the book
spread = pd.DataFrame.from_dict(ob_metrics['spread']).T
spread.columns=['Spread']
spread.head()
Out[13]:
Spread
2021-07-05T13:06:46.571Z 5.0
2021-07-05T13:06:47.918Z 5.0
2021-07-05T13:06:49.414Z 5.0
2021-07-05T13:06:51.077Z 3.0
2021-07-05T13:06:52.426Z 3.0

De esta manera podemos decir mientrás más cerrado sea el spread más liquido puede ser el activo en ese momento ya estan mas cerca de poner de acuerdo los participantes del mercado. Como podemos observar en nuestros datos el spread tiende a ser relativamente elevado llegando a tocar valores incluso de $12$, sin embargo es importante considerar la escala de los datos analizados, ya que al tratarse del BTCUSDT maneja magnitudes muy amplias.

4.7. Midprice

El midprice generalmente se define como el valor promedio entre el bid price y el ask price definido para el top of the book, y es justamente este precio el cual alcanza a reflejar el valor de cotización a ese momento, ya que alcanza a percibir y poderar de igual manera las expectativas tanto de compradores como de vendedores. Matemáticamente podemos expresar el midprice como:

$$\frac{\hat{\text{ask price}} + \hat{\text{bid price}}}{2}$$
In [14]:
### Let's see the midprice for top of the book
midprice = pd.DataFrame.from_dict(ob_metrics['midprice']).T
midprice.columns=['Midprice']
midprice.head()
Out[14]:
Midprice
2021-07-05T13:06:46.571Z 28272.5
2021-07-05T13:06:47.918Z 28272.5
2021-07-05T13:06:49.414Z 28272.5
2021-07-05T13:06:51.077Z 28276.5
2021-07-05T13:06:52.426Z 28276.5

De los datos obtenidos para el BTCUSDT podemos observar que el valor del midprice se encuentra fluctuando sobre valores entre $\$28,270$ y $\$28,444.5$ realmente no alcanza a presentar tantos cambios ya que pondera de igual manera las expectativas de los compradores como de los vendedores.

4.8. Volume Inbalance

In [15]:
### Let's see the volume inbalance for top of the book
volume_inbalance = pd.DataFrame.from_dict(ob_metrics['volume_inbalance']).T
volume_inbalance.columns=['Volume Inbalance']
volume_inbalance.head()
Out[15]:
Volume Inbalance
2021-07-05T13:06:46.571Z 0.503140
2021-07-05T13:06:47.918Z 0.503140
2021-07-05T13:06:49.414Z 0.503140
2021-07-05T13:06:51.077Z 0.495451
2021-07-05T13:06:52.426Z 0.495451

4.9. Weighted Midprice

In [16]:
### Let's see the weighted midprice for top of the book
weighted_mid = pd.DataFrame.from_dict(ob_metrics['weighted_mid']).T
weighted_mid.columns=['Weighted Midprice']
weighted_mid.head()
Out[16]:
Weighted Midprice
2021-07-05T13:06:46.571Z 28270.077503
2021-07-05T13:06:47.918Z 28270.077503
2021-07-05T13:06:49.414Z 28270.077503
2021-07-05T13:06:51.077Z 28277.997729
2021-07-05T13:06:52.426Z 28277.997729

4.10. VWAP (Volume Weighted Average Midprice)

In [17]:
### Let's see the VWAP for top of the book
vwap = pd.DataFrame.from_dict(ob_metrics['vwap']).T
vwap.columns=['VWAP']
vwap.head()
Out[17]:
VWAP
2021-07-05T13:06:46.571Z 28274.922497
2021-07-05T13:06:47.918Z 28274.922497
2021-07-05T13:06:49.414Z 28274.922497
2021-07-05T13:06:51.077Z 28275.002271
2021-07-05T13:06:52.426Z 28275.002271

4.11. Statistical Moments

In [18]:
### Let's see the statistical moments for total orderbooks
stats_moments = pd.DataFrame.from_dict(ob_metrics['stats_moments']).T
stats_moments.columns=['Stats']
stats_moments.head()
Out[18]:
Stats
median 0.357747
var 0.012448
skewness 0.392483
kurtosis 0.196053

4.12. OHLCV (Open-High-Low-Close-Volume)

La estructura de precios OHLCV (Open-High-Low-Close-Volume), básicamente nos ayuda a entender como es que se están moviendo los precios para cada agrupación en el tiempo, es una función de agregación que agrupa y nos ayuda a entender la estructura del precio en cada momento. Para el caso de los orderbooks tenemos que esta estructura hace referencia al volumen que se encuentran colocando compradores y vendedores, no como tal al volumen de adquisición.

In [19]:
### Let's see the OHLCV price structure
ob_metrics['ohlcv'].head()
Out[19]:
Midprice Volume
open high low close Volume
2021-07-05 13:06:00+00:00 28272.5 28282.5 28272.5 28282.5 583.699038
2021-07-05 13:07:00+00:00 28296.0 28324.0 28285.0 28324.0 2607.552512
2021-07-05 13:08:00+00:00 28324.0 28324.0 28300.0 28312.0 2633.889410
2021-07-05 13:09:00+00:00 28317.0 28331.0 28313.5 28331.0 2512.929262
2021-07-05 13:10:00+00:00 28333.0 28352.0 28333.0 28338.5 2667.233642

Al contar con solamente una hora de información, se optó por agrupar para cada cambio en los mismo del tiempo, si bien pareciera que no hay mucho cambio de un tiempo a otro (sobre todo por las maginitudes a las que se mueve el BTCUSDT) la realidad es que definiendo estos deltas de $1$ min si alcanzan a percibirse determinados cambios, sobre todo en términos de volumen.


5. Public Trades Metrics


Al igual que con el cálculo de las métricas del orderbook para el cálcilo de las de public trades también se realizó una función que logre otorgar al usuario de manera precisa y concisa los valores que se desean obtener.

In [20]:
### Let's define all the metric calculations.
pt_metrics = fn.get_pt_metrics(pt_data)

print(f'The keys for this ob metrics are: {list(pt_metrics.keys())}')
The keys for this ob metrics are: ['buy_count', 'sell_count', 'total_count', 'diff_count', 'buy_volume', 'sell_volume', 'total_volume', 'diff_volume', 'ohlcv', 'stats_moments']

5.1. Buy Trade Count

Esta métrica básicamente esta referenciada a un conteo de todas aquellas operaciones de trading que se registraron del lado del comprador. Con la intención de verla de una manera mas concisa se decide agrupar por hora.

In [21]:
### Let's see the trade buy count
buy_count = pt_metrics['buy_count']
buy_count.head()
Out[21]:
price
hour
0 5789
1 5892
2 5740
3 6229
4 6265

Como podemos observar la mayoría de operaciones de compra por hora para el BTCUSDT se mueven entre $5,000$ y %7,000$ transacciones, pareciera ser una medida bastante normal para los niveles que maneja regularmente el activo. A partir de estos valores también se podría comenzar a intuir las expectativas del mercado para la gente que quiera comprar, mientrás mas demanda exista naturalmente el precio tenderá a subir.

5.2. Sell Trade Count

El sell trade count funciona como un análogo del buy trade count solo que esta refleja las expectativas de mercado por parte de los vendedores del activo.

In [22]:
### Let's see the trade sell count
sell_count = pt_metrics['sell_count']
sell_count.head()
Out[22]:
price
hour
0 6211
1 6008
2 6160
3 5671
4 5735

Misma conclusión, las escalas sobre las cuales se mueven las expectativas de los vendedores se encuentran entre $4,000$ y $6,000$ operaciones, un poco más baja en comparación con la contraparte de compra. Esto nos indicaría que en este día en particular la gente compró o realizó más operaciones de compra.

5.3. Total Trade Count

El total trade count básicamente corresponde a la suma de ambas partes, tanto la compradora como la vendedora, esta métrica si bien nos ayuda a darnos cuenta de la magnitud de compras realizadas por día, nos nos refleja las expectativas de cada parte del mercado.

In [23]:
### Let's see the trade total count
total_count = pt_metrics['total_count']
total_count.head()
Out[23]:
price
hour
0 12000
1 11900
2 11900
3 11900
4 12000

En general cada hora del día se mantiene sobre los mismos niveles, entre $11,000$ y $13,000$ operaciones, no se alcanza a percibir alguna situación extraña.

5.4. Difference Trade Count

Esta métrica ya nos ayuda más a entender como se interelacionan la parte compradora y vendedora del mercado entre sí. El cálculo se propuso como:

$$\text{Buy Trade Count} - \text{Sell Trade Count}$$

De manera que si encontramos valores negativos para la diferencia estaríamos hablando de que en ese punto del tiempo se registraron más operaciones de venta que de compra.

In [24]:
### Let's see the trade diff count
diff_count = pt_metrics['diff_count']
diff_count.head()
Out[24]:
price
hour
0 -422
1 -116
2 -420
3 558
4 530

De los resultados arrojados se puede observar que existe una magnitud de inbalance considerablemente mayor a favor de los compradores ($2,216$ operaciones mas) en comparativa con el mejor desbalance para los vendedores con ($832$ operaciones mas). Esto nos indica al menos para este día analizado que sistemáticamente existió una mayor cantidad de compradores, cuestión que muy probablemente llego a impactar en el precio de cierre a final de la jornada.

5.5. Buy Trade Volume

In [25]:
### Let's see the trade buy volume
buy_volume = pt_metrics['buy_volume']
buy_volume.head()
Out[25]:
amount
hour
0 385.22900
1 313.65801
2 315.67582
3 298.66418
4 286.82202

5.6. Sell Trade Volume

In [26]:
### Let's see the trade sell volume
sell_volume = pt_metrics['sell_volume']
sell_volume.head()
Out[26]:
amount
hour
0 512.57474
1 437.77102
2 415.92031
3 430.73225
4 482.09504

5.7. Total Trade Volume

In [27]:
### Let's see the trade total volume
total_volume = pt_metrics['total_volume']
total_volume.head()
Out[27]:
amount
hour
0 897.80374
1 751.42903
2 731.59613
3 729.39643
4 768.91706

5.8. Difference Trade Volume

In [28]:
### Let's see the trade diff volume
diff_volume = pt_metrics['diff_volume']
diff_volume.head()
Out[28]:
amount
hour
0 -127.34574
1 -124.11301
2 -100.24449
3 -132.06807
4 -195.27302

5.9. OHLCV (Open-High-Low-Close-Volume)

In [29]:
### Let's see the OHLCV price structure
ohlcv_pt = pt_metrics['ohlcv']
ohlcv_pt.head()
Out[29]:
price amount
open high low close amount
timestamp
2022-05-10 00:00:00 30075.19 30842.21 29758.78 30770.010 897.80374
2022-05-10 01:00:00 30722.91 31340.94 30702.40 30900.682 751.42903
2022-05-10 02:00:00 30883.21 31390.16 30797.60 31033.700 731.59613
2022-05-10 03:00:00 31045.10 31152.46 30640.13 30664.400 729.39643
2022-05-10 04:00:00 30682.08 31340.86 30602.80 31215.350 768.91706

5.10. Statistical Moments

In [30]:
### Let's see the statistical moments for total public trades
stats_moments_pt = pd.DataFrame.from_dict(pt_metrics['stats_moments']).T
stats_moments_pt.columns=['Stats']
stats_moments_pt.head()
Out[30]:
Stats
median -125.646475
var 4238.110708
skewness 0.161939
kurtosis -0.578542


6. Visualizations


6.1. OrderBook Chart

In [31]:
### Let's see the orderbook chart. I'll select the first one with a depth of 5
vz.plot_orderbook(list(ob_data.values())[0], 5)

6.2. Public Trades Chart

In [32]:
### Let's see the public trades chart. I'll select to see just a 1 hour behaviour
warnings.filterwarnings("ignore")
vz.plot_publictrades(pt_data, hours=1)


7. References


[1] Munnoz, 2020. Python project template. https://github.com/iffranciscome/python-project. (2021).